home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / Drtf / DHTMLHandler.cpp < prev    next >
Text File  |  1996-07-05  |  44KB  |  1,735 lines

  1. // DHTMLHandler.cpp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include "Dvibrant.h"
  6. #include "DFile.h"
  7. #include "DRichProcess.h"
  8. #include "DRichViewNu.h"
  9. #include "DHTMLHandler.h"
  10. #include "DHTMLprocess.h"
  11. #include "rtfchars.h" 
  12. #include "DRichMoreStyle.h"
  13.  
  14.  
  15.     
  16. class DHTMLsetup  
  17. {
  18. public:
  19.     DHTMLsetup();
  20. };
  21.  
  22. static DHTMLsetup* gHTMLsetup = NULL;
  23. #if 0
  24. static DHTMLsetup theSetup; // construct it now !
  25. #endif
  26.  
  27. DHTMLsetup::DHTMLsetup()
  28. {
  29.     DHTMLprocess::InitKeys(); 
  30.     //ReadOutputMap("gen", gGenCharMap);
  31.   //gOutMap= gGenCharMap;
  32.     ////
  33.     //DRichprocess::gGenCharMap= DRichprocess::ReadOutputMap("gen");
  34.     //DRichprocess::gSymCharMap= DRichprocess::ReadOutputMap("sym");
  35.     gHTMLsetup = this;
  36. }
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43. //class  DHTMLHandler
  44.  
  45.  
  46. char* DHTMLHandler::IsRich(char* buf, ulong buflen)
  47. {
  48. // HTML doesn't have a fixed magic string -- usage is variable
  49. // some diagnostic strings (all case-insensitive)
  50. // </a> </head>
  51. // <html>  <head>  <body>  <title> 
  52. // uncertain: </ <a
  53. //    href=
  54.  
  55.     char* cp, *atbuf= buf;
  56.     if (buflen==0) buflen= StrLen(buf);
  57.     ulong len = buflen;
  58.     while (len>3) {
  59.         cp= (char*) MemChr(atbuf,'<',len);
  60.         if (cp) {
  61.             if (cp[1] == '/' && (cp[2] == 'a' || cp[2] == 'A') && cp[3] == '>') 
  62.                 return buf;
  63.             else if (!StrNICmp( cp, "<html>", 6)) return buf;
  64.             else if (!StrNICmp( cp, "<head>", 6)) return buf;
  65.             else if (!StrNICmp( cp, "<title>", 7)) return buf;
  66.             else if (!StrNICmp( cp, "<p>", 3)) return buf;   // ?? weak test but need
  67.             else if (!StrNICmp( cp, "<a href=", 9)) return buf;
  68.             //if (!StrNICmp( cp, "<a ", 3)) {  
  69.             //  unsigned long    at;
  70.             //    if (Nlm_StrngPos( cp, "</a>", 3, false, &at)) return true;
  71.             //    }
  72.             cp++;
  73.             len -= (cp - atbuf);
  74.             atbuf = cp;
  75.             }
  76.         else 
  77.             return NULL;    
  78.         }
  79.     return NULL;
  80. }
  81.  
  82.             
  83.  
  84. DHTMLHandler::DHTMLHandler( DRichView* itsDoc, DFile* savefile) :
  85.     DRichHandler( itsDoc, savefile)
  86. {
  87.     fFormatName = "HTML";
  88.     fMinDataToProcess= 128; // no fixed min, need to look at data...
  89.     if (!gHTMLsetup) gHTMLsetup= new DHTMLsetup();
  90. }
  91.  
  92. DHTMLHandler::~DHTMLHandler()
  93. {
  94. }
  95.  
  96.     
  97. DRichprocess* DHTMLHandler::NewProcessor( DFile* itsFile, Nlm_MonitorPtr progress)
  98. {
  99.     fProcessor = new DHTMLprocess( itsFile, fDoc, progress);
  100.     return fProcessor;
  101. }
  102.  
  103.  
  104. Boolean DHTMLHandler::ProcessData( char* cbeg, char* cend, Boolean endOfData, 
  105.                                                 ulong& dataRemaining) 
  106. {
  107.     char  * cp;  
  108.  
  109.     fcsave= 0;    
  110.     fclen= cend - cbeg; // + 1;
  111.     cp= cend; 
  112.     if (!endOfData) {
  113.         if ((fclen==0) || ( fProcessStage == kAtStart && fclen<fMinDataToProcess)) 
  114.             return false;
  115.         // scan for last newline and stop there !!
  116. #if 1 //TEST w/out << NEED THIS for at least some
  117.         while (cp - cbeg > fLastScanto && !(*cp == '\n' || *cp == '\r')) cp--;
  118.         if (cp < cend && (*cp == '\n' || *cp == '\r')) cp++;
  119. #endif
  120.         }
  121.  
  122. #if 1 //TEST w/out << NEED THIS for at least some
  123.     if (cp - cbeg <= fLastScanto) {
  124.         fLastScanto= cend - cbeg;  
  125.         if (!endOfData) return false; // !??! don't process line w/o end
  126.         else cp= cend; 
  127.         }
  128. #endif
  129.  
  130. #if 0 // bad nulls ??
  131.     if (*cp) cp++;
  132.     fcsave= *cp; 
  133.     *cp= 0;
  134. #endif
  135.  
  136.     fclen= cp - cbeg; // + 1; 
  137.     
  138.     if (fclen && fDocFile) {
  139.         if (cbeg[fclen-1] == 0) fclen--;  //?? 
  140.         fDocFile->WriteData( cbeg, fclen);
  141.         }    
  142.         
  143.     return this->ProcessData2( cp, cbeg, cend, endOfData, dataRemaining);
  144. }
  145.  
  146.  
  147.  
  148.  
  149.  
  150. // class DHTMLprocess
  151.  
  152.  
  153.  
  154. //static char        gGenCharMap[rtfSC_MaxChar];
  155. //static char * gOutMap = gGenCharMap;
  156.  
  157. DHTMLprocess::DHTMLprocess( DFile* itsFile, DRichView* itsDoc, Nlm_MonitorPtr progress) :
  158.     DRichprocess( itsFile, itsDoc, progress),
  159.     fStop(0), fTokenLen(0), fListType(0), fListNum(0), fDLStyle(0), fQuote(0),
  160.     fCurControl(0), fCurField(0), fLastField(0), fPicLink(0), fAnchorLink(0),
  161.     fURLstore(NULL), fNamestore(NULL), fFormURL(NULL), fGoplusStore(NULL),
  162.     fMethodstore(NULL), fValstore(NULL), fTypestore(NULL), fOptionstore(NULL),
  163.     fSizestore(NULL),fMaxlengthstore(NULL),fRowsstore(NULL),fColsstore(NULL),
  164.     fPushSize(0), fPushBuf(NULL), fPushBufstore(NULL),
  165.     fInHead(true), fInParam(false), fInForm(false), fInControl(false), fIsMap(false),
  166.     fIsChecked(false), fSelectitem(0), fCurItem(0), fIsMultiple(false),
  167.     fTurnOn(true), fIsIndex(false), fPreformat(false)
  168.     //fOutMap= DRichprocess::gGenCharMap;
  169. }
  170.  
  171.  
  172.  
  173.     
  174. DHTMLprocess::~DHTMLprocess()
  175. {
  176.     MemFree(fURLstore);
  177.     MemFree(fNamestore);
  178.     MemFree(fMethodstore);
  179.     MemFree(fGoplusStore);
  180.     MemFree(fFormURL);
  181.     MemFree(fValstore);
  182.     MemFree(fTypestore);
  183.     MemFree(fOptionstore);
  184.     MemFree(fPushBufstore);
  185.     MemFree(fSizestore);
  186.     MemFree(fMaxlengthstore);
  187.     MemFree(fRowsstore);
  188.     MemFree(fColsstore);
  189. }
  190.  
  191.  
  192. //static
  193. short DHTMLprocess::Hash( char    *s)
  194. {
  195.     char    c;
  196.     short    val = 0;
  197.     while ((c = *s++) != '\0') val += (int) tolower(c);
  198.     return (val);
  199. }
  200.  
  201. //static
  202. void DHTMLprocess::InitKeys()
  203. {
  204.     HTMLKey    *rp;
  205.     
  206.     for (rp = htmlKeys; rp->htmlKStr != NULL; rp++) {
  207.         rp->htmlKHash = Hash(rp->htmlKStr);
  208.         }
  209.     for (rp = htmlAmperChars; rp->htmlKStr != NULL; rp++) {
  210.         rp->htmlKHash = Hash(rp->htmlKStr);
  211.         }
  212. }
  213.  
  214.  
  215. void DHTMLprocess::Lookup( char    *s, HTMLKey* keyset)
  216. {
  217.     HTMLKey    *rp;
  218.     short    hash;
  219.     
  220. #ifdef COMP_BOR  /* ?? dgg */  
  221.     int LIBCALL (*cmp)(const char*,const char*);
  222. #else
  223. #ifdef COMP_SYMC
  224.   int (* LIBCALL cmp)(const char*, const char*);
  225. #else
  226.     int (*cmp)(const char*,const char*);
  227. #endif
  228. #endif
  229.     if (keyset == htmlAmperChars) cmp= Nlm_StringCmp;
  230.     else cmp= Nlm_StringICmp;
  231.     
  232.     fClass = tokUnknown;
  233.     if (*s == 0) return;
  234.     hash = Hash(s);
  235.     for (rp = keyset; rp->htmlKStr != NULL; rp++) {
  236.         if (hash == rp->htmlKHash && cmp(s, rp->htmlKStr) == 0) {
  237.             fClass = tokControl;
  238.             fMajor = rp->htmlKMajor;
  239.             fMinor = rp->htmlKMinor;
  240.             fStop  = rp->htmlKStop;
  241.             return;
  242.         }
  243.     }
  244. }
  245.  
  246.  
  247.  
  248.  
  249. void DHTMLprocess::Pushback(char c) // private
  250. {
  251.     if (c != EOF) {
  252.         fPushedChar = c;
  253.         }
  254. }
  255.  
  256.  
  257.  
  258. enum {
  259.     kGotNone = 0,
  260.     kGotToken,
  261.     kGotParam
  262.     };
  263.     
  264. short DHTMLprocess::GotTokenOrParam() // private
  265. {
  266.     if (fTokenLen>0) { // need to process last token ! 
  267.         fTokenBuf[fTokenLen] = '\0';
  268.         long i, tokenlen= fTokenLen;
  269.         fTokenLen= 0;
  270.         if (fInParam) {
  271.             switch (fCurField) {
  272.             
  273.                 case htmlIsMap:
  274.                     fIsMap= true;
  275.                     break;
  276.                     
  277.                 case htmlAction:
  278.                 case htmlImageSrc:
  279.                 case htmlHref:
  280.                     for (i=0; i<tokenlen; i++) if (fTokenBuf[i]<' ') fTokenBuf[i]= ' ';
  281.                     MemFree(fURLstore);
  282.                     fURLstore= StrDup(fTokenBuf);
  283.                     break;
  284.  
  285.                 //case htmlInput:
  286.                 //case htmlSelect:
  287.                 //case htmlTextarea:
  288.                 
  289.                     // form tags -- stuff data where ??
  290.                 case htmlTitle:
  291.                 case htmlName:
  292.                     MemFree(fNamestore);
  293.                     fNamestore= StrDup(fTokenBuf);
  294.                     break;
  295.   
  296.                 case htmlMethod:
  297.                     MemFree(fMethodstore);
  298.                     fMethodstore= StrDup(fTokenBuf);
  299.                     break;
  300.                 case htmlValue:
  301.                     MemFree(fValstore);
  302.                     fValstore= StrDup(fTokenBuf);
  303.                     if (fLastField==htmlOption) fCurField= fLastField;
  304.                     break;
  305.                 case htmlType:
  306.                     MemFree(fTypestore);
  307.                     fTypestore= StrDup(fTokenBuf);
  308.                     break;
  309.                 
  310.                 case htmlChecked:
  311.                     fIsChecked= true;
  312.                     break;
  313.                 case htmlSelected:
  314.                     fSelectitem= fCurItem;
  315.                     break;
  316.                 case htmlMultiple:
  317.                     fIsMultiple= true;
  318.                     break;
  319.                 case htmlSize:
  320.                     MemFree(fSizestore);
  321.                     fSizestore= StrDup(fTokenBuf);
  322.                     break;
  323.                 case htmlMaxlength:
  324.                     MemFree(fMaxlengthstore);
  325.                     fMaxlengthstore= StrDup(fTokenBuf);
  326.                     break;
  327.                 case htmlRows:
  328.                     MemFree(fRowsstore);
  329.                     fRowsstore= StrDup(fTokenBuf);
  330.                     break;
  331.                 case htmlCols:
  332.                     MemFree(fColsstore);
  333.                     fColsstore= StrDup(fTokenBuf);
  334.                     break;
  335.                     
  336.                 case htmlOption:
  337.                     fTokenBuf[tokenlen++]= '\t';
  338.                     fTokenBuf[tokenlen]= '\0';
  339.                     if (!fOptionstore) fOptionstore= StrDup(fTokenBuf);
  340.                     else StrExtendCat( &fOptionstore, fTokenBuf);
  341.                             // need to collect BOTH option text and values !
  342.                     if (fValstore) {
  343.                         tokenlen= StrLen( fValstore);
  344.                         StrCpy( fTokenBuf, fValstore);
  345.                         }
  346.                     else
  347.                         tokenlen= 0;
  348.                     fTokenBuf[tokenlen++]= '\t';
  349.                     fTokenBuf[tokenlen]= '\0';
  350.                     if (!fRowsstore) fRowsstore= StrDup(fTokenBuf);
  351.                     else StrExtendCat( &fRowsstore, fTokenBuf);
  352.                     break;
  353.  
  354.                 }
  355.             fInParam= false;
  356.             return kGotParam;
  357.             }
  358.         else {
  359.             Lookup( fTokenBuf, htmlKeys);     // sets class, major, minor 
  360.             return kGotToken;
  361.             }
  362.         }
  363.     else
  364.         return kGotNone;
  365. }
  366.  
  367.  
  368.  
  369. void DHTMLprocess::GetToken1() // private
  370. {
  371.     short    c;
  372.  
  373.     fClass = tokUnknown;   // initialize token vars  
  374.     fParam = tokNoParam;
  375.  
  376.     if (fPushedChar != EOF) {
  377.         c = fPushedChar;
  378.         fPushedChar = EOF;
  379.         }
  380.     else 
  381.         c= GetOneChar();
  382.          
  383.     switch ( c ) {
  384.     
  385.         case EOF:
  386.             fClass = tokEOF;
  387.             fMajor = tokEOF;
  388.             return;
  389.             
  390.         case tokBreakInData:
  391.             fClass= tokEOF;
  392.             fMajor= tokBreakInData;
  393.             return;
  394.                             
  395.         case '>':
  396.             {
  397.             if (fInControl && fQuote) goto cInQuote;
  398.             if (!fInControl) goto cHandleText;
  399.             if (GotTokenOrParam() != kGotNone) {
  400.                 Pushback(c);
  401.                 return;
  402.                 }
  403.             if (fCurField == htmlOption) { // fCurControl == htmlSelect && 
  404.                 Pushback('='); // turn following text into option Param...
  405.                 return; 
  406.                 }
  407.             fInControl= false;
  408.             fClass = tokControl;
  409.             fMajor = htmlEndControl;
  410.             fMinor = -1;
  411.             return;
  412.             }
  413.         
  414.         case '<':
  415.             if (fInControl && fQuote) goto cInQuote;
  416.             if (fQuote == (char)234) { // kInFormText
  417.                 fInControl= false;
  418.                 this->handleLinkAttr( fCurControl);  
  419.                 }
  420.             fInControl= true;
  421.             fTurnOn= true;
  422.             fInParam= false;
  423.             fQuote= 0;
  424.             fCurControl= 0;
  425.             fCurField= 0;
  426.             fTokenLen= 0;
  427.             fPicLink= 0;
  428.             //fAnchorLink= 0;
  429.             fClass = tokDropchar;
  430.             return;
  431.  
  432.         default: 
  433.         
  434.             if (fInControl) {
  435. cInQuote:                    
  436.                 // !! need to deal with complex  options in <Control ... > syntax
  437.                 // e.g. <a href="some.string" name="some.string" etc. > text here </a>
  438.                 // e.g. < IMG SRC ="triangle.gif" ALT="Warning:"> text here...
  439.               // < A HREF="Go">< IMG SRC ="Button"> Press to start</A>
  440.                 
  441.               if ( (fQuote && c != fQuote)  
  442.                   || (fInParam && c != fQuote && c != '"' && c != '\'' && c > ' ') 
  443.                || isalnum(c) ) {
  444.                   // store in token buf until unquoted
  445.                     if (fTokenLen<kMaxTokenBuf) fTokenBuf[fTokenLen++] = c;
  446.                     if (fQuote == (char)234) { // kInFormText
  447.                         goto labelNoControl; // also stuff c into texthandler stream
  448.                         }
  449.                     else
  450.                         fClass = tokDropchar;
  451.                     return; 
  452.                   }
  453.  
  454.                 if (GotTokenOrParam() == kGotToken) {
  455.                   Pushback( c);  // ! need to handle terminator char
  456.                   return;  
  457.                     }
  458.                     
  459.                 if (fQuote && c == fQuote) {
  460.                     // must be sure we handle unquote ! after storing param
  461.                     fQuote = 0;
  462.                     fClass = tokDropchar;
  463.                     return; 
  464.                     }
  465.  
  466.                 switch ( c ) {
  467.                     case '/': fTurnOn= false; break;
  468.                     case '=': fInParam= true; break;
  469.                     case '"':  
  470.                     case '\'': 
  471.                             // ?? these may be good only if (fInParam) ???
  472.                         if (fQuote) fQuote= 0; // end of quote..
  473.                         else fQuote= c; 
  474.                         break;
  475.                     
  476.                     default:
  477.                         //if (isspace(c))  break; 
  478.                         break;
  479.                     }
  480.                     
  481.                 fClass = tokDropchar;
  482.                 return; 
  483.                  }
  484.                  
  485.              else {
  486. labelNoControl:
  487.                  switch ( c ) {
  488.  
  489.                 case '&':
  490.                     //wordat= fTokenBuf+fTokenLen;
  491.                     fTokenLen= 0;
  492.                     do { 
  493.                         c = GetOneChar(); 
  494.                         if (fTokenLen<kMaxTokenBuf) fTokenBuf[fTokenLen++] = c;
  495.                     } while (c > EOF && isalnum(c));
  496.                     fTokenBuf[fTokenLen] = '\0';
  497.                     Lookup( fTokenBuf, htmlAmperChars);     // sets class, major, minor 
  498.                     return;
  499.  
  500.                 case '\t':
  501.                     fClass = tokControl;
  502.                     fMajor = htmlSpecialChar;
  503.                     fMinor = htmlTab;
  504.                     return;
  505.                     
  506.                 case '\r': 
  507.                 case '\n': //NEWLINE:
  508.                     if (fPreformat) {
  509.                         fClass = tokControl;
  510.                         fMajor = htmlSpecialChar;
  511.                         fMinor = htmlNewline;
  512.                         }
  513.                     else if (fTextSize>0) { 
  514.                             // messy fix for that cutesy horizontal bar 
  515.                         if ( fTextSize > 15 && fText[15] == '_'
  516.                               && fText[1] == '_' && fText[fTextSize-2] == '_') {
  517.                             fTextSize= 0;
  518.                             handleSpecialChar( htmlHBar);    
  519.                             fClass = tokDropchar;
  520.                             }
  521.                         else 
  522.                             // put space in, if this isn't new parag
  523.                             goto cHandleSpace;
  524.                         }    
  525.                     else
  526.                         fClass = tokDropchar;
  527.                     return;
  528.                 
  529.                 case ' ':
  530.                 cHandleSpace:
  531.                     if (fPreformat || fLastChar != ' ') {
  532.                         fClass = tokText;
  533.                         fMajor = ' ';
  534.                         fMinor = ' '; // MapChar( c);
  535.                         }
  536.                     else
  537.                         fClass = tokDropchar;
  538.                     return;
  539.                     
  540.                 case '\0':
  541.                     fClass = tokDropchar;
  542.                     return;
  543.                     
  544.                 default:
  545.                 cHandleText:
  546.                     fClass = tokText;
  547.                     fMajor = c;
  548.                     fMinor = c; // MapChar( c);
  549.                     return;
  550.                  }
  551.              }
  552.              }
  553. }
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563. short DHTMLprocess::GetOneChar()
  564. {
  565. #if 1
  566.     if (fPushSize && fPushBuf) {
  567.         short c= (unsigned char) *fPushBuf; // must be unsigned !!
  568.         fPushSize--;
  569.         fPushBuf++;
  570.         return c;
  571.         }
  572.     else
  573.         return DRichprocess::GetOneChar();
  574. #else
  575.     short    c;
  576.  
  577.     if (fDataBuffer) {
  578.         c= (unsigned char) *fDataBuffer; // must be unsigned !!
  579.         if (fDataSize) {    // for counted data
  580.             fDataSize--;
  581.             fDataBuffer++;
  582.             if (!fDataSize) fDataBuffer= NULL; //  so EOF next time
  583.             }
  584.         else if (c) fDataBuffer++; // for null-term data
  585.         else if (!fEndOfData) c= tokBreakInData;
  586.         else c= EOF;
  587.         }
  588.     else if (fDataFile) 
  589.         c = fgetc( fDataFile->fFile);
  590.     else {
  591.         if (!fEndOfData) c= tokBreakInData;
  592.         else c= EOF;
  593.         }
  594.     return (c);
  595. #endif
  596. }
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604. void DHTMLprocess::handleTextClass()
  605. {
  606.     if (IsNewStyle()) StoreStyle(fOldStyleRec.style, FALSE);  
  607.     
  608.     if (fMinor != rtfSC_nothing)
  609.         PutStdChar(fMinor); 
  610.     else {
  611.         char    buf[128];
  612.         if (fMajor < 128)    /* in ASCII range */
  613.             sprintf (buf, "[[%c]]", fMajor);
  614.         else
  615.             sprintf (buf, "[[\\'%02x]]", fMajor);
  616.         PutLitStr (buf);
  617.         }
  618.     fLastChar= fMajor;
  619. }
  620.  
  621.  
  622. void DHTMLprocess::handleControlClass()
  623. {
  624.     switch (fMajor) {
  625.         case htmlDocAttr    : handleDocAttr(fMinor); break;
  626.         case htmlLinkAttr    : handleLinkAttr(fMinor); break;
  627.         case htmlFormAttr    : handleFormAttr(fMinor); break;
  628.         case htmlCharAttr    : handleCharAttr(fMinor); break;
  629.         case htmlParAttr    : handleParAttr(fMinor); break;
  630.         case htmlListAttr    : handleListAttr(fMinor); break;
  631.         case htmlPictAttr    : handlePictAttr(fMinor); break;
  632.         case htmlSpecialChar: handleSpecialChar(fMinor); break;
  633.         case htmlEndControl: handleEndControl(fMinor); break;
  634.         }
  635. }
  636.  
  637.  
  638.  
  639. void DHTMLprocess::handleEndControl(short attr)
  640. {
  641.     // e.g, > end of any control
  642.  
  643.     if (fCurControl == htmlForm
  644.      || fCurControl == htmlInput 
  645.      //|| fCurControl == htmlSelect 
  646.      //|| fCurControl == htmlTextarea
  647.      ) {
  648.         // call here AFTER DNetHTMLprocess::handleEndControl
  649.         this->handleFormAttr( fCurControl);  //?? !? why this mess here
  650.         }
  651.         
  652.     else if (fCurControl == htmlImage) {
  653.         short kind;
  654.         char * dummypict = (char*) MemNew( 1);
  655.         *dummypict= 0;
  656.         if (fAnchorLink) kind= DPictStyle::kPictNetLink;
  657.         else kind= DPictStyle::kPictNetPic;
  658.         DPictStyle* thePic= new DPictStyle( kind, dummypict, 1, true);   
  659.  
  660.         if (!fParaCount) NewParagraph();
  661.             
  662.         if (fPicLink) {
  663.             Nlm_RecT loc;
  664.             Nlm_LoadRect( &loc, 0, 0, 35, 22); // top is to fetch picture
  665.             thePic->AddLink( DPictStyle::kPictNetPic, fPicLink, loc);
  666.             if (fAnchorLink) {
  667.                 Nlm_LoadRect( &loc, 0, 23, 35, 35); // bottom is to fetch link info
  668.                 thePic->AddLink( DPictStyle::kPictNetLink, fAnchorLink, loc);
  669.                 }
  670.             fPicLink= 0;
  671.             }
  672.             
  673.             // !? in html, is damn url suffix supposed indicate TYPE of data !?
  674.             // or can we assume all these are GIF pictures ?
  675.         fStyleRec.style.ismap= fIsMap;
  676.         StoreStyleObject( thePic, 35, 35);
  677.         }
  678.  
  679.     fCurControl= 0;
  680.     fCurField= 0;
  681.     fIsMap= false;
  682. }
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689. void DHTMLprocess::handleDocAttr(short attr)
  690. {
  691.     switch (attr) {
  692.     
  693.         case htmlHTML:     
  694.             if (fTurnOn) fCurControl= attr;
  695.             break;
  696.         case htmlHead:    fInHead= fTurnOn; break;
  697.         case htmlBody:  fInHead= false; break;
  698.  
  699.         case htmlTitle:      
  700.             // ! this htmlTitle can occur both in Head and Body/Anchor
  701.             if (fTurnOn) {
  702.                 fCurControl= attr; //??
  703.                 fNamestore= (char*) MemFree(fNamestore);  
  704.                 }
  705.             else {
  706. #if 0
  707.                 fTitle= fNamestore;
  708.                 fNamestore= NULL;
  709. #else                
  710.                 if (fTextSize) { // fInHead &&
  711.                     MemFree(fTitle);  
  712.                     fText[fTextSize]= '\0';
  713.                     fTitle= StrDup( fText); 
  714.                     fTextSize= 0;
  715.                     }
  716. #endif
  717.                 }
  718.             break;
  719.             
  720.         case htmlIsIndex: {
  721.             fIsIndex= true;
  722.             MemFree(fPushBufstore);
  723.             fPushBufstore= StrDup(" <A HREF=?>Click here to query</A> ");
  724.             fPushBuf= fPushBufstore;
  725.             fPushSize= StrLen(fPushBuf);
  726.             //MemFree(fURLstore);
  727.             //fURLstore= StrDup("#");
  728.             // entire doc is somehow flagged as a query document, and need
  729.             // some kind of button to send query to server from this doc !?
  730.             // go->fType= kTypeQuery;
  731.             }
  732.             break;
  733.             
  734.         case htmlBase: 
  735.             break;
  736.  
  737.         case htmlLink: 
  738.         case htmlNextID: 
  739.             break;
  740.             
  741.         //case htmlHref: // !! bug in processing tokens -- arrive here after finding Link/HREF !
  742.         }
  743. }
  744.  
  745.  
  746.  
  747. #if 0
  748. ///////////  html forms stuff ///////////////
  749. ///// convert to gopher ask forms ///////////
  750.  
  751. <form  action="partial-url-to-handle-data" method=get or post> 
  752.  
  753. <input name="variable_name"> // one line text input (type=text)
  754. <input type=text name="variable_name" value='default text'> // one line text input
  755.     >> Ask: variable_name:\t default text
  756.  
  757. <input type=password name="variable_name-name"> // one line password text input
  758.     >> AskP: variable_name
  759.     
  760. <input type=submit value='button title'> // button to send form
  761.     >> default ask form "okay" button
  762. <input type=reset value='button title'>  // button to clear current choices
  763.     >> no ask equivalent
  764.     
  765. <input type=checkbox name=variable_name value="box title" checked>
  766.     >> Select: box title:0 or 1
  767.     
  768. <input type=radio name=var_name value='title 1'>
  769. <input type=radio name=var_name value='title 2'>
  770.     >> Choose: var_name: \t title 1 \t title 2 ...
  771.     
  772. <textarea name=var_name cols=40 rows=2>  // text input box
  773. default text
  774. </textarea>
  775.   >> AskL: var_name \t default text
  776.   
  777. <select>
  778. <option selected> name1
  779. <option> name2
  780. <option value=n3> name2
  781. </select>
  782.     >> Choose: var_name: \t name1 \t name2 ...
  783.  
  784.  
  785. </form>
  786.  
  787.         // forms tags
  788.   htmlLinkAttr,    htmlForm, "form", kSlashStop, 0,
  789.       htmlLinkAttr,    htmlInput, "input", kNoStop, 0,
  790.       htmlLinkAttr,    htmlSelect, "select", kSlashStop, 0,
  791.         htmlLinkAttr,    htmlTextarea, "textarea", kSlashStop, 0,
  792.         htmlLinkAttr,    htmlValue, "value", kNoStop, 0,
  793.         htmlLinkAttr,    htmlType, "type", kNoStop, 0,
  794.         htmlLinkAttr,    htmlOption, "option", kNoStop, 0,
  795.         htmlLinkAttr,    htmlAction, "action", kNoStop, 0,
  796.         htmlLinkAttr,    htmlMethod, "method", kNoStop, 0,
  797.  
  798. #endif
  799.  
  800.  
  801.  
  802.  
  803. void DHTMLprocess::handleFormAttr(short attr)
  804. {
  805.     char buf[512];
  806.     DWindow* fWin;
  807.     DControlStyle* cs;
  808.     
  809.     switch (attr) {
  810.     
  811.         case htmlForm: 
  812.             fCurControl= attr;
  813.             fCurField= attr;
  814.             fInForm= fTurnOn;
  815.             if (fInForm) {
  816.                 if (fInControl) {
  817.                     fURLstore= (char*) MemFree(fURLstore);  
  818.                     fMethodstore= (char*) MemFree(fMethodstore);  
  819.                     fFormURL= (char*) MemFree(fFormURL);
  820.                     //fGoplusStore= (char*) MemFree(fGoplusStore);
  821.                     //fGoplusStore= StrDup("+ASKHTML:\n");  
  822.                     PushStyle();
  823.                     fIsChecked= fIsMultiple= false; fSelectitem= 0;
  824.                     }
  825.                 else {
  826.                     // <FORM METHOD=get/post/localexec ACTION="proto://path/function opts">  
  827.                     cs = NULL;
  828.                     fWin= fDoc->GetWindow();
  829.                     cs= new DHiddenCStyle( fWin); 
  830.                     if (!fMethodstore) cs->ControlData( "GET", fURLstore);  
  831.                     else cs->ControlData( fMethodstore, fURLstore);  
  832.                     cs->Install();
  833.                     StoreStyleObject( cs, cs->Width(), cs->Height());
  834.                     }
  835.                 }
  836.             else {
  837.                 //fStyleRec.style.color= 0; // ?? 
  838.                 //fStyleRec.style.linkid= 0;                
  839.                 //PopStyle();
  840.                 }
  841.             break;
  842.  
  843. //   need to collect other Forms control tags:
  844. // input: TYPE= NAME= VALUE= CHECKED  SIZE=  MAXLENGTH=
  845. // option: VALUE= (or value after ">")  SELECTED
  846. // select: NAME=  SIZE= (#items to show)  MULTIPLE
  847. // textarea: NAME=  COLS= ROWS=  
  848.  
  849.         case htmlInput:
  850.             if (fInControl) {
  851.               fCurControl= attr; //?? 
  852.                 fCurField= attr;
  853.                 fTypestore= (char*) MemFree(fTypestore);  
  854.                 fNamestore= (char*) MemFree(fNamestore);  
  855.                 fMethodstore= (char*) MemFree(fMethodstore);  
  856.                 fOptionstore= (char*) MemFree(fOptionstore);  
  857.                 fValstore= (char*) MemFree(fValstore);  
  858.                 fSizestore= (char*) MemFree(fSizestore);  
  859.                 fMaxlengthstore= (char*) MemFree(fMaxlengthstore);  
  860.                 fRowsstore= (char*) MemFree(fRowsstore);  
  861.                 fColsstore= (char*) MemFree(fColsstore);  
  862.                 fIsChecked= fIsMultiple= false; fSelectitem= 0;
  863.                 }
  864.                 
  865.             else {
  866.             // this are HandleEndControl, e.g., at "...>", methods, 
  867.             // not !fInControl start methods (e.g., at "</control..." 
  868.             
  869.                 cs = NULL;
  870.                 fWin= fDoc->GetWindow();
  871.                 
  872.                 if (!fTypestore || StrICmp( fTypestore, "text")==0) {
  873.                     // <input type=text name="variable_name" value='default text' size=10>
  874.                     cs= new DEditTextCStyle( fWin); 
  875.                     if (fSizestore) cs->fWidth= atol(fSizestore);
  876.                     else if (fMaxlengthstore) cs->fWidth= atol(fMaxlengthstore);
  877.                     cs->ControlData( fNamestore, fValstore); // installs in view !?
  878.                     }
  879.  
  880.                 else if (StrICmp( fTypestore, "password")==0) {
  881.                     // <input type=password name="variable_name">  
  882.                     cs= new DPasswordCStyle( fWin); 
  883.                     if (fSizestore) cs->fWidth= atol(fSizestore);
  884.                     else if (fMaxlengthstore) cs->fWidth= atol(fMaxlengthstore);
  885.                     cs->ControlData( fNamestore, fValstore); // installs in view !?
  886.                     }
  887.  
  888.                 else if (StrICmp( fTypestore, "hidden")==0) {
  889.                     // <input type=hidden name="variable_name" value="whatever">  
  890.                     cs= new DHiddenCStyle( fWin); 
  891.                     cs->ControlData( fNamestore, fValstore); 
  892.                     }
  893.  
  894.                 else if (StrICmp( fTypestore, "submit")==0) {
  895.                     // <input type=submit value='button title'> // button to send form
  896.                     cs= new DDefaultButtonCStyle( fWin); 
  897.                     if (!fValstore) cs->ControlData( fNamestore, "Submit"); 
  898.                     else cs->ControlData( fNamestore, fValstore); 
  899.                     }
  900.                     
  901.                 else if (StrICmp( fTypestore, "reset")==0) {
  902.                     // <input type=reset value='button title'>  // button to clear current choices
  903.                     cs= new DButtonCStyle( fWin); 
  904.                     if (!fValstore) cs->ControlData( fNamestore, "Reset"); 
  905.                     else cs->ControlData( fNamestore, fValstore); 
  906.                     }
  907.  
  908.                 else if (StrICmp( fTypestore, "checkbox")==0) {
  909.                     //<input type=checkbox name=variable_name value="box title" checked>
  910.                     cs= new DCheckboxCStyle( fWin); 
  911.                     cs->fSelected= fIsChecked;
  912.                     if (!fValstore)  cs->ControlData( fNamestore, "on");  
  913.                     else cs->ControlData( fNamestore, fValstore); 
  914.                     }
  915.                     
  916.                 else if (StrICmp( fTypestore, "radio")==0) {
  917.                     //<input type=radio name=var_name value='title 2'>
  918.                     cs= new DRadioCStyle( fWin); 
  919.                     cs->fSelected= fIsChecked;
  920.                     if (!fValstore)  cs->ControlData( fNamestore, "on");  
  921.                     else cs->ControlData( fNamestore, fValstore); 
  922.                     }
  923.                     
  924.                 else if (StrICmp( fTypestore, "file")==0) {
  925.                     //<input type=file name=default_file_name value='anything'>
  926.                     cs= new DFileCStyle( fWin); 
  927.                     if (!fValstore)  cs->ControlData( fNamestore, "default-file"); 
  928.                     else cs->ControlData( fNamestore, fValstore); 
  929.                     }
  930.                     
  931.                 if (cs) {
  932.                     cs->Install();
  933.                     StoreStyleObject( cs, cs->Width(), cs->Height());
  934.                     }
  935.                 
  936.  
  937.                 }
  938.             break;
  939.  
  940.  
  941.         case htmlSelect: 
  942.                 //<select name="myname">
  943.                 //<option selected> name1
  944.                 //<option> name2
  945.                 //<option value=n3> name3
  946.                 //</select>
  947.             if (fTurnOn) { // fInControl
  948.               fCurControl= attr; //?? 
  949.                 fCurField= attr;
  950.                 fCurItem= 0;
  951.                 fLastField= 0;
  952.                 //fSomething= fTurnOn;
  953.                 fNamestore= (char*) MemFree(fNamestore); 
  954.                 fOptionstore= (char*) MemFree(fOptionstore); 
  955.                 fValstore= (char*) MemFree(fValstore);  
  956.                 fSizestore= (char*) MemFree(fSizestore);  
  957.                 fMaxlengthstore= (char*) MemFree(fMaxlengthstore);  
  958.                 fRowsstore= (char*) MemFree(fRowsstore);  
  959.                 fColsstore= (char*) MemFree(fColsstore);  
  960.                 fIsChecked= fIsMultiple= false; fSelectitem= 0;
  961.                 }
  962.             else {
  963.                 fLastField= 0;
  964.                 cs = NULL;
  965.                 fWin= fDoc->GetWindow();
  966.                 cs= new DPopupCStyle( fWin); 
  967.                     // ! need to options == popup selections -> from fOptionstore
  968.                 cs->fSelected= fSelectitem;
  969.                 cs->ControlData( fNamestore, fOptionstore, fRowsstore); //? fOption not fValstore
  970.                 cs->Install();
  971.                 StoreStyleObject( cs, cs->Width(), cs->Height());
  972.                 }
  973.             break;
  974.             
  975.         case htmlOption: 
  976.             if (fInControl) {
  977.                 fCurField= attr;
  978.                 fCurItem++;
  979.                 fValstore= (char*) MemFree(fValstore);  
  980.                 }
  981.             else {
  982.                 fLastField= 0;
  983.                 }
  984.             break;
  985.  
  986.  
  987.         case htmlTextarea: 
  988.                 //<textarea name=var_name cols=40 rows=2>  
  989.                 //default text
  990.                 //</textarea>
  991.             if (fTurnOn) { // fInControl)
  992.               fCurControl= attr; //?? 
  993.                 fCurField= attr;
  994.                 //fSomething= fTurnOn;
  995.                 fNamestore= (char*) MemFree(fNamestore);  
  996.                 fValstore= (char*) MemFree(fValstore);  
  997.                 fSizestore= (char*) MemFree(fSizestore);  
  998.                 fMaxlengthstore= (char*) MemFree(fMaxlengthstore);  
  999.                 fRowsstore= (char*) MemFree(fRowsstore);  
  1000.                 fColsstore= (char*) MemFree(fColsstore);  
  1001.                 fIsChecked=  fIsMultiple= false; fSelectitem= 0;
  1002.                 }
  1003.             else {
  1004.                 cs = NULL;
  1005.                 fWin= fDoc->GetWindow();
  1006.                 cs= new DDialogTextCStyle( fWin); 
  1007.                 cs->ControlData( fNamestore, fValstore); 
  1008.                 if (fColsstore) cs->fWidth= atol(fColsstore); // # chars wide
  1009.                 if (fRowsstore) cs->fHeight= atol(fRowsstore); // # chars tall
  1010.                 cs->Install();
  1011.                 StoreStyleObject( cs, cs->Width(), cs->Height());
  1012.               }
  1013.             break;
  1014.  
  1015.             
  1016.         case htmlMethod:
  1017.             fCurField= attr;
  1018.             // this is GET or POST -- only those two?
  1019.             break;
  1020.             
  1021.         case htmlAction:
  1022.             fCurField= attr;
  1023.             fURLstore= (char*) MemFree(fURLstore);  
  1024.             break;
  1025.             
  1026.         case htmlChecked:
  1027.             fIsChecked= true;
  1028.             fCurField= attr;
  1029.             break;
  1030.         case htmlSelected:
  1031.             fSelectitem= fCurItem;
  1032.             //if (fCurField!=htmlOption) fCurField= attr;
  1033.             break;
  1034.         case htmlMultiple:
  1035.             fIsMultiple= true;
  1036.             fCurField= attr;
  1037.             break;
  1038.             
  1039.         case htmlSize:
  1040.         case htmlMaxlength:
  1041.         case htmlRows:
  1042.         case htmlCols:
  1043.         // case htmlName: // handled        
  1044.         case htmlValue:
  1045.             //if (fCurField!=htmlOption) 
  1046.             fLastField= fCurField;
  1047.             fCurField= attr;
  1048.             break;
  1049.  
  1050.             
  1051.         case htmlType:
  1052.              // record param
  1053.             fCurField= attr;
  1054.             fTypestore= (char*) MemFree(fTypestore);  
  1055.             break;
  1056.  
  1057.         }
  1058. }
  1059.  
  1060.  
  1061.  
  1062. void DHTMLprocess::handleLinkAttr(short attr)
  1063. {
  1064.     char buf[512];
  1065.     
  1066.     switch (attr) {
  1067.     
  1068.         case htmlAnchor: 
  1069.             if (fTurnOn) {
  1070.                 fAnchorLink= 0;
  1071.                 fCurControl= attr;
  1072.                 // DAMN, need to push/pop something here -- having style changes inside
  1073.                 // anchor causes it to disappear now !!!
  1074.                 PushStyle();
  1075.                 //PutLitCharWithStyle('['); // [] for debugging
  1076.                 }
  1077.             else {
  1078.                 fStyleRec.style.color= 0; // ?? 
  1079.                 fStyleRec.style.linkid= 0;                
  1080.                 //PutLitCharWithStyle(']'); // [] for debugging
  1081.                 PopStyle();
  1082.                 fAnchorLink= 0;
  1083.                 }
  1084.             break;
  1085.  
  1086.         case htmlHref: 
  1087.             fCurField= attr;
  1088.             // store: ="url://bob.was/here"
  1089.             fURLstore= (char*) MemFree(fURLstore);  
  1090.             break;
  1091.  
  1092.         case htmlName: 
  1093.             fCurField= attr;
  1094.             // store: ="some name"
  1095.             fNamestore= (char*) MemFree(fNamestore);  
  1096.             break;
  1097.             
  1098.         case htmlRel: 
  1099.             fCurField= attr;
  1100.             //fNamestore= (char*) MemFree(fNamestore);  
  1101.             break;
  1102.         case htmlRev: 
  1103.             fCurField= attr;
  1104.             //fNamestore= (char*) MemFree(fNamestore);  
  1105.             break;
  1106.         case htmlUrn: 
  1107.             fCurField= attr;
  1108.             //fNamestore= (char*) MemFree(fNamestore);  
  1109.             break;
  1110.         case htmlMethods: 
  1111.             fCurField= attr;
  1112.             //fNamestore= (char*) MemFree(fNamestore);  
  1113.             break;
  1114.         //case htmlTitle: // handled in other section !! 
  1115.         }
  1116. }
  1117.  
  1118.  
  1119.  
  1120. void DHTMLprocess::handlePictAttr(short attr)
  1121. {
  1122.     switch (attr) {
  1123.         case htmlImage: {
  1124.             // main tag
  1125.             fCurControl= attr;
  1126.             fCurField= attr;
  1127.             }
  1128.             break;
  1129.             
  1130.         case htmlImageSrc: 
  1131.             // this is the URL to remote picture ??
  1132.             fCurField= attr;
  1133.             // store: ="url://bob.was/here"
  1134.             fURLstore= (char*) MemFree(fURLstore);  
  1135.             break;
  1136.             
  1137.         case htmlImageAlt: 
  1138.             // text name for non-graphic clients?
  1139.         case htmlIsMap: 
  1140.         case htmlAlign: 
  1141.             fCurField= attr;
  1142.             break;
  1143.         }
  1144. }
  1145.  
  1146. #ifdef TESTDEF
  1147. #define  DEFAULTS() { DefaultParag(); DefaultStyle(); GetNlmFont(); }
  1148. #else
  1149. #define DEFAULTS()    {}
  1150. #endif
  1151.             
  1152. void DHTMLprocess::handleParAttr(short attr)
  1153. {
  1154.     switch (attr) {
  1155.     
  1156.         case htmlH1: 
  1157.             if (fTurnOn) {
  1158.                 PushStyle();
  1159.                 handleSpecialChar(htmlPage);
  1160.                 DefaultStyle();
  1161.                 fParaFmt.just= 'c';
  1162.                 fParaFmt.spaceBefore= 20; 
  1163.                 fStyleRec.style.bold= true;
  1164.                 fStyleRec.fontsize= 2 * kDefaultFontsize;
  1165.                 }
  1166.             else {
  1167.                 fParaFmt.spaceAfter= 10; 
  1168.                 PutLitCharWithStyle('\n');
  1169.                 NewParagraph();
  1170.                 fParaFmt.just= 'l';
  1171.                 fParaFmt.spaceBefore= 0; 
  1172.                 fParaFmt.spaceAfter= 0; 
  1173.                 PopStyle();
  1174.                 DEFAULTS();
  1175.                 }
  1176.             NewStyle();
  1177.             break;
  1178.             
  1179.         case htmlH2: 
  1180.              if (fTurnOn) {
  1181.                 PushStyle();
  1182.                 PutLitCharWithStyle ('\n');
  1183.                 NewParagraph();
  1184.                 DefaultStyle();
  1185.                 fParaFmt.spaceBefore= 10; 
  1186.                 fStyleRec.style.bold= true;
  1187.                 fStyleRec.fontsize= 6 + kDefaultFontsize;
  1188.                 }
  1189.             else {
  1190.                 fParaFmt.spaceAfter= 5; 
  1191.                 PutLitCharWithStyle ('\n');
  1192.                 NewParagraph();
  1193.                 fParaFmt.spaceBefore= 0; 
  1194.                 fParaFmt.spaceAfter= 0; 
  1195.                 PopStyle();
  1196.                 DEFAULTS();
  1197.                 }
  1198.             NewStyle();
  1199.             break;
  1200.                         
  1201.         case htmlH3: 
  1202.              if (fTurnOn) {
  1203.                 PushStyle();
  1204.                 PutLitCharWithStyle ('\n');
  1205.                 NewParagraph();
  1206.                 DefaultStyle();
  1207.                 fParaFmt.spaceBefore= 6; 
  1208.                 fStyleRec.style.italic= true;
  1209.                 fStyleRec.fontsize= 6 + kDefaultFontsize;
  1210.                 }
  1211.             else {
  1212.                 fParaFmt.spaceAfter= 4; 
  1213.                 PutLitCharWithStyle ('\n');
  1214.                 NewParagraph();
  1215.                 fParaFmt.spaceBefore= 0; 
  1216.                 fParaFmt.spaceAfter= 0; 
  1217.                 PopStyle();
  1218.                 DEFAULTS();
  1219.                 }
  1220.             NewStyle();
  1221.             break;
  1222.     
  1223.         case htmlH4:                          
  1224.             if (fTurnOn) {
  1225.                 PushStyle();
  1226.                 PutLitCharWithStyle('\n');
  1227.                 NewParagraph();
  1228.                 DefaultStyle();
  1229.                 fStyleRec.style.bold= true;
  1230.                 fStyleRec.fontsize= 2 + kDefaultFontsize;
  1231.                 }
  1232.             else {
  1233.                 fParaFmt.spaceAfter= 4; 
  1234.                 PutLitCharWithStyle('\n');
  1235.                 NewParagraph();
  1236.                 fParaFmt.spaceBefore= 0; 
  1237.                 fParaFmt.spaceAfter= 0; 
  1238.                 PopStyle();
  1239.                 DEFAULTS();
  1240.                 }
  1241.             NewStyle();
  1242.             break;
  1243.  
  1244.         case htmlH5: 
  1245.             if (fTurnOn) {
  1246.                 PushStyle();
  1247.                 PutLitCharWithStyle('\n');
  1248.                 NewParagraph();
  1249.                 DefaultStyle();
  1250.                 fStyleRec.fontsize= 2 + kDefaultFontsize;
  1251.                 //fStyleRec.style.italic= true;
  1252.                 }
  1253.             else {
  1254.                 fParaFmt.spaceAfter= 2; 
  1255.                 PutLitCharWithStyle('\n');
  1256.                 fParaFmt.spaceBefore= 0; 
  1257.                 fParaFmt.spaceAfter= 0; 
  1258.                 PopStyle();
  1259.                 DEFAULTS();
  1260.                 }
  1261.             NewStyle();
  1262.             break;
  1263.             
  1264.         case htmlH6: 
  1265.             if (fTurnOn) {
  1266.                 PushStyle();
  1267.                 PutLitCharWithStyle('\n');
  1268.                 NewParagraph();
  1269.                 DefaultStyle();
  1270.                 //fStyleRec.style.bold= true;
  1271.                 }
  1272.             else {
  1273.                 fParaFmt.spaceAfter= 2; 
  1274.                 PutLitCharWithStyle('\n');
  1275.                 PopStyle();
  1276.                 fParaFmt.spaceBefore= 0; 
  1277.                 fParaFmt.spaceAfter= 0; 
  1278.                 DEFAULTS();
  1279.                 }
  1280.             NewStyle();
  1281.             break;
  1282.  
  1283.  
  1284.         case htmlAddress: 
  1285.             if (fTurnOn) {
  1286.                 PushStyle();
  1287.                 PutLitCharWithStyle('\n');
  1288.                 NewParagraph();
  1289.                 DefaultStyle();
  1290.                 fParaFmt.just= 'r';
  1291.                 fStyleRec.style.italic= true;
  1292.                 }
  1293.             else {
  1294.                 PutLitCharWithStyle('\n');
  1295.                 NewParagraph();
  1296.                 fParaFmt.just= 'l';
  1297.                 PopStyle();
  1298.                 DEFAULTS();
  1299.                 }
  1300.             NewStyle();
  1301.             break;
  1302.  
  1303.         case htmlBlockquote: 
  1304.             if (fTurnOn) {
  1305.                 PushStyle();
  1306.                 PutLitCharWithStyle('\n');
  1307.                 fParaFmt.spaceBefore= 10; 
  1308.                 //fParaFmt.borderleft= TRUE;
  1309.                 NewParagraph();
  1310.                 fParaFmt.leftInset  += 30;  
  1311.                 fParaFmt.rightInset += 50;  
  1312.                 fStyleRec.style.italic= true;
  1313.                 }
  1314.             else {
  1315.                 fParaFmt.spaceAfter= 10; 
  1316.                 PutLitCharWithStyle('\n');
  1317.                 NewParagraph();
  1318.                 fParaFmt.spaceBefore= 0; 
  1319.                 fParaFmt.spaceAfter= 0; 
  1320.                 //fParaFmt.borderleft= false;
  1321.                 fParaFmt.leftInset = MAX( 0, fParaFmt.leftInset-30);  
  1322.                 fParaFmt.rightInset= MAX( 0, fParaFmt.rightInset-50);  
  1323.                 PopStyle();
  1324.                 }
  1325.             NewStyle();
  1326.             break;
  1327.  
  1328.         case htmlPreformat: 
  1329.             fPreformat= fTurnOn;
  1330.             handleCharAttr(htmlFixedwidth);
  1331.             NewStyle();
  1332.             break;
  1333.  
  1334.         case htmlLinewidth: 
  1335.             // this is attrib of htmlPreformat
  1336.             break;
  1337.  
  1338.             // lists/tables ?
  1339.          case htmlDL:
  1340.              if (fTurnOn) {
  1341.                 fParaFmt.leftInset  += kDefTabstop;  
  1342.                 fParaFmt.firstInset -= kDefTabstop;  
  1343.                  fDLStyle= htmlDL;
  1344.                  }
  1345.              else {
  1346.                 PutLitCharWithStyle('\n');
  1347.                 NewParagraph();
  1348.                 fParaFmt.leftInset  = MAX(0, fParaFmt.leftInset - kDefTabstop);  
  1349.                 fParaFmt.firstInset = MIN(0, fParaFmt.firstInset + kDefTabstop);  
  1350.                  }
  1351.                  
  1352.              // attribs of htmlDL
  1353.          case htmlCompact:
  1354.              fDLStyle= htmlCompact;
  1355.              break;
  1356.          case htmlDT:
  1357.             PutLitCharWithStyle('\n');
  1358.             NewParagraph();
  1359.             fParaFmt.leftInset  = MAX(0, fParaFmt.leftInset - kDefTabstop);  
  1360.             fParaFmt.firstInset = MIN(0, fParaFmt.firstInset + kDefTabstop);  
  1361.             break;
  1362.          case htmlDD:
  1363.              if (true) { //fDLStyle != htmlCompact) {
  1364.                  PutLitCharWithStyle('\n');
  1365.                 NewParagraph();
  1366.                 fParaFmt.leftInset  += kDefTabstop;  
  1367.                 fParaFmt.firstInset -= kDefTabstop;  
  1368.                 }
  1369.             PutStdCharWithStyle('\t');
  1370.              break;
  1371.         }
  1372. }
  1373.  
  1374.  
  1375. void DHTMLprocess::handleListAttr(short attr)
  1376. {
  1377.     switch (attr) {
  1378.     
  1379.         case htmlNumList:
  1380.         case htmlMenu:
  1381.         case htmlDir:
  1382.         case htmlBullList:
  1383.             fListType= attr;
  1384.             fListNum= 0;
  1385.              if (fTurnOn) {
  1386.                 PutLitCharWithStyle('\n');
  1387.                 NewParagraph();
  1388.                 fParaFmt.leftInset  += kDefTabstop;  
  1389.                 fParaFmt.firstInset -= kDefTabstop - 20;  
  1390.                  }
  1391.              else {
  1392.                 PutLitCharWithStyle('\n');
  1393.                 NewParagraph();
  1394.                 fParaFmt.leftInset  = MAX(0, fParaFmt.leftInset-kDefTabstop);  
  1395.                 fParaFmt.firstInset = MIN(0, fParaFmt.firstInset+kDefTabstop+20);  
  1396.                 PutLitCharWithStyle('\n');
  1397.                 NewParagraph();
  1398.                  }        
  1399.             break;
  1400.  
  1401.     
  1402.         case htmlListItem:
  1403.             PutLitCharWithStyle('\n');
  1404.             NewParagraph();
  1405.             fListNum++; // count isn't nested, nor is fListType !!
  1406.             // !!? need push/pop for list vars !!!!!!
  1407.             if (fListType == htmlNumList) {
  1408.                 char nums[30];
  1409.                 sprintf( nums, "%d\t", fListNum);
  1410.                 PutLitStr( nums);
  1411.                 }
  1412.             else {
  1413.                 PutStdCharWithStyle( gGenCharMap[rtfSC_bullet]); //'•'
  1414.                 PutStdChar('\t');
  1415.                 }
  1416.             break;
  1417.             
  1418.         }
  1419. }
  1420.  
  1421.  
  1422.  
  1423.  
  1424. void DHTMLprocess::handleCharAttr(short attr)
  1425. {
  1426.     switch (attr) {
  1427.  
  1428.     case htmlFixedwidth: //rtfFontNum:
  1429.         if (fTurnOn) {
  1430.             PushStyle();
  1431.             fStyleRec.fontname= "courier";
  1432.             fStyleRec.fontfamily= "Modern";
  1433.             fStyleRec.fontsize= kDefaultFontsize; 
  1434.             }
  1435.         else {
  1436.             PopStyle();
  1437.             } 
  1438.         NewStyle();
  1439.         //(void) GetNlmFont();  
  1440.         break;
  1441.                 
  1442.     case htmlSampleFont:
  1443.      case htmlUserFont:
  1444.         if (fTurnOn) {
  1445.             PushStyle();
  1446.             fStyleRec.fontname= "helvetica";
  1447.             fStyleRec.fontfamily= "Swiss";
  1448.             fStyleRec.fontsize= kDefaultFontsize; 
  1449.             }
  1450.         else {
  1451.             PopStyle();
  1452.             } 
  1453.         NewStyle();
  1454.         //(void) GetNlmFont();  
  1455.         break;
  1456.  
  1457.     case htmlPlain:
  1458.         DefaultStyle();
  1459.         NewStyle();
  1460.         break;
  1461.         
  1462.     case htmlVarFont: //rtfSmallCaps:
  1463.         NewStyle();
  1464.         fStyleRec.style.smallcaps= fTurnOn;
  1465.         break;
  1466.  
  1467.     case htmlEmphasis:
  1468.     case htmlBold:
  1469.         NewStyle();
  1470.         fStyleRec.style.bold= fTurnOn;
  1471.         break;
  1472.         
  1473.     case htmlDefineFont:
  1474.     case htmlCiteFont:
  1475.         // ?? also use diff font??
  1476.     case htmlItalic:
  1477.         NewStyle();
  1478.         fStyleRec.style.italic= fTurnOn;
  1479.         break;
  1480.     case htmlMoreEmphasis: //rtfUnderline:
  1481.         NewStyle();
  1482.         fStyleRec.style.bold= fTurnOn;
  1483.         if (fTurnOn) fStyleRec.style.underline = DRichStyle::kUnderline;
  1484.         else fStyleRec.style.underline= 0;
  1485.         break;
  1486.     case htmlInvisible:
  1487.         NewStyle();
  1488.         fStyleRec.style.hidden= fTurnOn;
  1489.         break;
  1490.     }
  1491. }
  1492.  
  1493.  
  1494. void DHTMLprocess::handleSpecialChar(short code)
  1495. {
  1496.     switch (code) {
  1497.         case htmlPar: 
  1498.             fParaFmt.spaceAfter += 5; 
  1499.             PutLitCharWithStyle('\n');
  1500.             NewParagraph();
  1501.             fParaFmt.spaceAfter -= 5; 
  1502.             fLastChar= ' ';
  1503.             break;
  1504.         case htmlNewline:
  1505.             PutLitCharWithStyle('\n');
  1506.             NewParagraph();
  1507.             fLastChar= ' ';
  1508.             break;
  1509.             
  1510.         case htmlHBar:
  1511.             fParaFmt.borderstyle = DParagraph::kBorderSingle; 
  1512.             fParaFmt.borderbottom = TRUE; 
  1513.             PutLitCharWithStyle('\n');
  1514.             PutLitChar(' ');
  1515.             NewParagraph();
  1516.             fParaFmt.borderstyle = DParagraph::kNoBorder; 
  1517.             fParaFmt.borderbottom = FALSE; 
  1518.             PutLitCharWithStyle('\n');
  1519.             NewParagraph();
  1520.             fLastChar= ' ';
  1521.             break;
  1522.             
  1523.         case htmlPage: 
  1524.             PutLitCharWithStyle ('\n');
  1525.             fParaFmt.newPage= TRUE;  
  1526.             NewParagraph();
  1527.             fParaFmt.newPage= FALSE; 
  1528.             fLastChar= ' ';
  1529.             break;
  1530.         case htmlTab:
  1531.             PutLitCharWithStyle('\t'); // tab isn't defined in HTML world...
  1532.             fLastChar= ' ';
  1533.             break;
  1534.  
  1535. #if 0
  1536.         case rtfSC_less:
  1537.             PutLitCharWithStyle('<');
  1538.             break;
  1539.         case rtfSC_greater:
  1540.             PutLitCharWithStyle('>');
  1541.             break;
  1542.         case rtfSC_quotedbl:
  1543.             PutLitCharWithStyle('"');
  1544.             break;
  1545.         case rtfSC_ampersand:
  1546.             PutLitCharWithStyle('&');
  1547.             break;
  1548. #endif
  1549.         default:
  1550.             PutLitCharWithStyle( gGenCharMap[code]);
  1551.             fLastChar= gGenCharMap[code];
  1552.             break;
  1553.         }
  1554. };
  1555.  
  1556.     
  1557.  
  1558.  
  1559. HTMLKey DHTMLprocess::htmlKeys[] =
  1560. {
  1561.         // document
  1562.     htmlDocAttr, htmlHTML,    "html", kSlashStop, 0,    
  1563.     htmlDocAttr, htmlTitle,    "title", kSlashStop, 0,    
  1564.     htmlDocAttr, htmlHead,    "head", kSlashStop, 0,    
  1565.     htmlDocAttr, htmlBody,    "body", kSlashStop, 0,    
  1566.     htmlDocAttr, htmlIsIndex,    "isindex", kNoStop, 0,    
  1567.     htmlDocAttr, htmlLink,    "link", kNoStop, 0,    
  1568.     htmlDocAttr, htmlNextID,    "nextid", kNoStop, 0,    
  1569.     htmlDocAttr, htmlBase,    "base", kNoStop, 0,    
  1570.       //htmlDocAttr,    htmlHref, "href=", kNoStop, 0,
  1571.     htmlDocAttr,    htmlComment,    "!", kNoStop, 0,
  1572.  
  1573.         // anchors & links
  1574.     htmlLinkAttr,    htmlAnchor,    "a", kSlashStop, 0,
  1575.       htmlLinkAttr,    htmlHref, "href", kNoStop, 0,
  1576.       htmlLinkAttr,    htmlName, "name", kNoStop, 0,
  1577.         htmlLinkAttr,    htmlRel, "rel", kNoStop, 0,
  1578.         htmlLinkAttr,    htmlRev, "rev", kNoStop, 0,
  1579.         htmlLinkAttr,    htmlUrn, "urn", kNoStop, 0,    
  1580.         htmlLinkAttr,    htmlMethods, "methods", kNoStop, 0,    
  1581.         //htmlLinkAttr, htmlTitle,    "title", kNoStop, 0,    
  1582.     
  1583.         // forms tags
  1584.   htmlFormAttr,    htmlForm, "form", kSlashStop, 0,
  1585.       htmlFormAttr,    htmlInput, "input", kNoStop, 0,
  1586.       htmlFormAttr,    htmlSelect, "select", kSlashStop, 0,
  1587.         htmlFormAttr,    htmlTextarea, "textarea", kSlashStop, 0,
  1588.         htmlFormAttr,    htmlValue, "value", kNoStop, 0,
  1589.         htmlFormAttr,    htmlType, "type", kNoStop, 0,
  1590.         htmlFormAttr,    htmlOption, "option", kNoStop, 0,
  1591.         htmlFormAttr,    htmlAction, "action", kNoStop, 0,
  1592.         htmlFormAttr,    htmlMethod, "method", kNoStop, 0,
  1593.         
  1594.         htmlFormAttr,    htmlChecked, "checked", kNoStop, 0,
  1595.         htmlFormAttr,    htmlSelected, "selected", kNoStop, 0,
  1596.         htmlFormAttr,    htmlMultiple, "multiple", kNoStop, 0,
  1597.         htmlFormAttr,    htmlSize, "size", kNoStop, 0,
  1598.         htmlFormAttr,    htmlMaxlength, "maxlength", kNoStop, 0,
  1599.         htmlFormAttr,    htmlRows, "rows", kNoStop, 0,
  1600.         htmlFormAttr,    htmlCols, "cols", kNoStop, 0,
  1601.         
  1602.         // font styles
  1603.     htmlCharAttr,    htmlBold,        "b",        kSlashStop, 0,
  1604.     htmlCharAttr,    htmlEmphasis,        "em",    kSlashStop,     0,
  1605.     htmlCharAttr,    htmlMoreEmphasis,        "strong",    kSlashStop,     0,
  1606.     htmlCharAttr,    htmlItalic,        "i",    kSlashStop,     0,
  1607.     htmlCharAttr,    htmlFixedwidth,        "tt",    kSlashStop,     0, // courier font !?
  1608.     htmlCharAttr,    htmlFixedwidth,        "code",    kSlashStop,     0, // courier font !?
  1609.     htmlCharAttr,    htmlSampleFont,        "samp",    kSlashStop,     0, 
  1610.     htmlCharAttr,    htmlUserFont,        "kbd",    kSlashStop,     0, 
  1611.     htmlCharAttr,    htmlVarFont,        "var",    kSlashStop,     0, 
  1612.     htmlCharAttr,    htmlDefineFont,        "dfn",    kSlashStop,     0, // bold
  1613.     htmlCharAttr,    htmlCiteFont,        "cite",    kSlashStop,     0, // italic
  1614.     htmlCharAttr,    htmlPlain,        "plaintext",    kSlashStop,     0,  
  1615.  
  1616.         // paragraph styles
  1617.     htmlParAttr,    htmlH1,    "h1", kSlashStop,     0,
  1618.     htmlParAttr,    htmlH2,    "h2", kSlashStop, 0,
  1619.     htmlParAttr,    htmlH3,    "h3", kSlashStop, 0,
  1620.     htmlParAttr,    htmlH4,    "h4", kSlashStop, 0,
  1621.     htmlParAttr,    htmlH5,    "h5", kSlashStop, 0,
  1622.     htmlParAttr,    htmlH6,    "h6", kSlashStop, 0,
  1623.     htmlParAttr,    htmlAddress,    "address", kSlashStop, 0,
  1624.     htmlParAttr,    htmlBlockquote,    "blockquote", kSlashStop, 0,
  1625.  
  1626.     htmlParAttr,    htmlPreformat,    "pre", kSlashStop, 0,
  1627.       htmlParAttr,    htmlLinewidth,    "width", kNoStop, 0,
  1628.     htmlParAttr,    htmlPreformat,        "listing",        kSlashStop, 0,  
  1629.     htmlParAttr,    htmlPreformat,        "xmp",        kSlashStop, 0,  
  1630.  
  1631.         // lists/tables ?
  1632.     htmlParAttr,    htmlDL,    "dl", kSlashStop, 0,
  1633.       htmlParAttr,    htmlCompact,    "compact",  kNoStop,0,
  1634.       htmlParAttr,    htmlDT,    "dt", kNoStop, 0,
  1635.       htmlParAttr,    htmlDD,    "dd", kNoStop, 0,
  1636.  
  1637.         // lists
  1638.     htmlListAttr,    htmlBullList,    "ul",  kSlashStop, 0,
  1639.     htmlListAttr,    htmlNumList,    "ol",  kSlashStop, 0,
  1640.     htmlListAttr,    htmlMenu,    "menu",  kSlashStop, 0,
  1641.     htmlListAttr,    htmlDir,    "dir",  kSlashStop, 0,
  1642.     htmlListAttr,    htmlListItem,    "li",  kNoStop,0,
  1643.  
  1644.         // pictures
  1645.     htmlPictAttr,    htmlImage,        "img", kNoStop,    0,
  1646.       htmlPictAttr,    htmlImageSrc,        "src", kNoStop,    0,
  1647.       htmlPictAttr,    htmlImageAlt,        "alt", kNoStop,    0,
  1648.         htmlPictAttr,    htmlAlign,        "aln", kNoStop,    0,
  1649.         htmlPictAttr,    htmlAlign,        "align", kNoStop,    0,
  1650.       htmlPictAttr,    htmlIsMap,        "ismap", kNoStop,    0,
  1651.  
  1652.         // characters
  1653.     htmlSpecialChar,    htmlPar,        "p", kNoStop,    0, // parag
  1654.     htmlSpecialChar,    htmlHBar,        "hr", kNoStop,    0, // paragraph rule
  1655.     0,        -1,            NULL,    0
  1656. };
  1657.  
  1658.     
  1659.  
  1660. HTMLKey DHTMLprocess::htmlAmperChars[] =
  1661. {
  1662.     htmlSpecialChar,    rtfSC_less, "lt;", kAmperChar,        0,
  1663.     htmlSpecialChar,    rtfSC_greater, "gt;", kAmperChar,        0,
  1664.     htmlSpecialChar,    rtfSC_ampersand, "amp;", kAmperChar,        0,
  1665.     htmlSpecialChar,    rtfSC_quotedbl, "quot;", kAmperChar,        0,
  1666.  
  1667.     htmlSpecialChar,    rtfSC_AE, "AElig;", kAmperChar,        0,
  1668.     htmlSpecialChar,    rtfSC_Aacute, "Aacute;", kAmperChar,        0,
  1669.     htmlSpecialChar,    rtfSC_Acircumflex, "Acirc;", kAmperChar,        0,
  1670.     htmlSpecialChar,    rtfSC_Agrave, "Agrave;", kAmperChar,        0,
  1671.     htmlSpecialChar,    rtfSC_Aring, "Aring;", kAmperChar,        0,
  1672.     htmlSpecialChar,    rtfSC_Atilde, "Atilde;", kAmperChar,        0,
  1673.     htmlSpecialChar,    rtfSC_Adieresis, "Auml;", kAmperChar,        0,
  1674.     htmlSpecialChar,    rtfSC_Ccedilla, "Ccedil;", kAmperChar,        0,
  1675.     htmlSpecialChar,    rtfSC_Eth, "ETH;", kAmperChar,        0,
  1676.     htmlSpecialChar,    rtfSC_Eacute, "Eacute;", kAmperChar,        0,
  1677.     htmlSpecialChar,    rtfSC_Ecircumflex, "Ecirc;", kAmperChar,        0,
  1678.     htmlSpecialChar,    rtfSC_Egrave, "Egrave;", kAmperChar,        0,
  1679.     htmlSpecialChar,    rtfSC_Edieresis, "Euml;", kAmperChar,        0,
  1680.     htmlSpecialChar,    rtfSC_Iacute, "Iacute;", kAmperChar,        0,
  1681.     htmlSpecialChar,    rtfSC_Icircumflex, "Icirc;", kAmperChar,        0,
  1682.     htmlSpecialChar,    rtfSC_Igrave, "Igrave;", kAmperChar,        0,
  1683.     htmlSpecialChar,    rtfSC_Idieresis, "Iuml;", kAmperChar,        0,
  1684.     htmlSpecialChar,    rtfSC_Ntilde, "Ntilde;", kAmperChar,        0,
  1685.     htmlSpecialChar,    rtfSC_Oacute, "Oacute;", kAmperChar,        0,
  1686.     htmlSpecialChar,    rtfSC_Ocircumflex, "Ocirc;", kAmperChar,        0,
  1687.     htmlSpecialChar,    rtfSC_Ograve, "Ograve;", kAmperChar,        0,
  1688.     htmlSpecialChar,    rtfSC_Oslash, "Oslash;", kAmperChar,        0,
  1689.     htmlSpecialChar,    rtfSC_Otilde, "Otilde;", kAmperChar,        0,
  1690.     htmlSpecialChar,    rtfSC_Odieresis, "Ouml;", kAmperChar,        0,
  1691.     htmlSpecialChar,    rtfSC_Thorn, "THORN;", kAmperChar,        0,
  1692.     htmlSpecialChar,    rtfSC_Uacute, "Uacute;", kAmperChar,        0,
  1693.     htmlSpecialChar,    rtfSC_Ucircumflex, "Ucirc;", kAmperChar,        0,
  1694.     htmlSpecialChar,    rtfSC_Ugrave, "Ugrave;", kAmperChar,        0,
  1695.     htmlSpecialChar,    rtfSC_Udieresis, "Uuml;", kAmperChar,        0,
  1696.     htmlSpecialChar,    rtfSC_Yacute, "Yacute;", kAmperChar,        0,
  1697.     htmlSpecialChar,    rtfSC_aacute, "aacute;", kAmperChar,        0,
  1698.     htmlSpecialChar,    rtfSC_acircumflex, "acirc;", kAmperChar,        0,
  1699.     htmlSpecialChar,    rtfSC_ae, "aelig;", kAmperChar,        0,
  1700.     htmlSpecialChar,    rtfSC_agrave, "agrave;", kAmperChar,        0,
  1701.     htmlSpecialChar,    rtfSC_aring, "aring;", kAmperChar,        0,
  1702.     htmlSpecialChar,    rtfSC_atilde, "atilde;", kAmperChar,        0,
  1703.     htmlSpecialChar,    rtfSC_adieresis, "auml;", kAmperChar,        0,
  1704.     htmlSpecialChar,    rtfSC_ccedilla, "ccedil;", kAmperChar,        0,
  1705.     htmlSpecialChar,    rtfSC_eacute, "eacute;", kAmperChar,        0,
  1706.     htmlSpecialChar,    rtfSC_ecircumflex, "ecirc;", kAmperChar,        0,
  1707.     htmlSpecialChar,    rtfSC_egrave, "egrave;", kAmperChar,        0,
  1708.     htmlSpecialChar,    rtfSC_eth, "eth;", kAmperChar,        0,
  1709.     htmlSpecialChar,    rtfSC_edieresis, "euml;", kAmperChar,        0,
  1710.     htmlSpecialChar,    rtfSC_iacute, "iacute;", kAmperChar,        0,
  1711.     htmlSpecialChar,    rtfSC_icircumflex, "icirc;", kAmperChar,        0,
  1712.     htmlSpecialChar,    rtfSC_igrave, "igrave;", kAmperChar,        0,
  1713.     htmlSpecialChar,    rtfSC_idieresis, "iuml;", kAmperChar,        0,
  1714.     htmlSpecialChar,    rtfSC_ntilde, "ntilde;", kAmperChar,        0,
  1715.     htmlSpecialChar,    rtfSC_oacute, "oacute;", kAmperChar,        0,
  1716.     htmlSpecialChar,    rtfSC_ocircumflex, "ocirc;", kAmperChar,        0,
  1717.     htmlSpecialChar,    rtfSC_ograve, "ograve;", kAmperChar,        0,
  1718.     htmlSpecialChar,    rtfSC_oslash, "oslash;", kAmperChar,        0,
  1719.     htmlSpecialChar,    rtfSC_otilde, "otilde;", kAmperChar,        0,
  1720.     htmlSpecialChar,    rtfSC_odieresis, "ouml;", kAmperChar,        0,
  1721.     htmlSpecialChar,    rtfSC_nothing, "szlig;", kAmperChar,        0, // ! no rtf equiv.
  1722.     htmlSpecialChar,    rtfSC_thorn, "thorn;", kAmperChar,        0,
  1723.     htmlSpecialChar,    rtfSC_uacute, "uacute;", kAmperChar,        0,
  1724.     htmlSpecialChar,    rtfSC_ucircumflex, "ucirc;", kAmperChar,        0,
  1725.     htmlSpecialChar,    rtfSC_ugrave, "ugrave;", kAmperChar,        0,
  1726.     htmlSpecialChar,    rtfSC_udieresis, "uuml;", kAmperChar,        0,
  1727.     htmlSpecialChar,    rtfSC_yacute, "yacute;", kAmperChar,        0,
  1728.     htmlSpecialChar,    rtfSC_ydieresis, "yuml;", kAmperChar,        0,
  1729.     0,        -1,            NULL,    0
  1730. };
  1731.  
  1732.  
  1733.  
  1734.